// ~ Package Declaration
// ==================================================

package com.wms.utils.lang;

import com.wms.data.WmsFrameworkException;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;


// ~ Comments
// ==================================================

/**
 * 
 * Class utility methods.
 * 
 * <pre>
 * 歷史紀錄：
 * 2009/1/12 Timothy
 * 	新建檔案
 * </pre>
 * 
 * @author <pre>
 * SD
 * 	Timothy
 * PG
 * 
 * UT
 * 
 * MA
 * </pre>
 * @version $Rev$
 * 
 *          <p/>
 *          $Id$
 * 
 */
public final class VSClassUtils {

	// ~ Static Fields
	// ==================================================

	// ~ Fields
	// ==================================================

	// ~ Constructors
	// ==================================================

	private VSClassUtils() {

	}

	// ~ Methods
	// ==================================================

	/**
	 * <pre>
	 * 2009/1/12 Timothy
	 * 	獲取 class 繼承超類的泛型宣告，迭代獲取最近的一個超類的泛型宣告列表
	 * </pre>
	 * 
	 * @param clazz
	 *          需要獲取泛型宣告的當前class
	 * @return {@link java.util.List}, 獲取最近的一個超類的泛型宣告列表
	 * @see #getGenericSuperClassActualType(Class, int)
	 */
	public static List<Class<?>> getGenericSupreClassActualTypes(Class<?> clazz) {

		if (VSObjectUtils.isNull(clazz)) {
			throw new WmsFrameworkException(new NullPointerException("clazz is not null!"));
		}

		List<Class<?>> resultClasses = new ArrayList<Class<?>>();

		Type genericSuperclass = clazz.getGenericSuperclass();

		if (genericSuperclass instanceof ParameterizedType) {

			for (Type type : ((ParameterizedType) genericSuperclass).getActualTypeArguments()) {
				resultClasses.add((Class<?>) type);
			}
		}
		else {

			Class<?> superClass = clazz.getSuperclass();

			if (superClass != Object.class) {

				resultClasses = VSClassUtils.getGenericSupreClassActualTypes(superClass);
			}
		}

		return resultClasses;
	}

	/**
	 * <pre>
	 * 2009/1/12 Timothy
	 * 	獲取 class 繼承超類的泛型宣告，迭代獲取最近的一個超類的泛型宣告列表中，索引參數&lt;code&gt;index&lt;/code&gt;指向的類別
	 * </pre>
	 * 
	 * @param clazz
	 *          需要獲取泛型宣告的當前class
	 * @param index
	 *          索引參數，指定獲取的參數類別
	 * @return 獲取 class 繼承超類的泛型宣告
	 * @throws com.WmsFrameworkException.VisualsoftFrameworkException
	 *           當 index < 0
	 * @see #getGenericSuperClassActualTypes(Class)
	 * @see #getGenericSuperClassActualType(Class, int, Class)
	 */
	public static Class<?> getGenericSuperClassActualType(Class<?> clazz, int index) {

		if (VSObjectUtils.isNull(clazz)) {
			throw new WmsFrameworkException(new NullPointerException("clazz is not null!"));
		}

		if (index < 0) {
			throw new WmsFrameworkException(new IllegalArgumentException("The index should be great or equals zero!"));
		}

		Class<?> resultClass = null;
		List<Class<?>> genericSupreClassActualTypes = VSClassUtils.getGenericSupreClassActualTypes(clazz);

		if (!genericSupreClassActualTypes.isEmpty()) {

			if (genericSupreClassActualTypes.size() > index) {

				resultClass = genericSupreClassActualTypes.get(index);
			}
			else {

				resultClass = VSClassUtils.getGenericSuperClassActualType(clazz.getSuperclass(), index);
			}
		}

		return resultClass;
	}

	/**
	 * <pre>
	 * 2009/1/12 Timothy
	 * 	獲取 class 繼承超類的泛型宣告，迭代獲取最近的一個超類的泛型宣告列表中第一個泛型類別
	 * </pre>
	 * 
	 * @param clazz
	 *          需要獲取泛型宣告的當前class
	 * @return 獲取 class 繼承超類的第一個泛型宣告
	 * @see #getGenericSuperClassActualType(Class, int)
	 */
	public static Class<?> getGenericSuperClassActualType(Class<?> clazz) {

		return VSClassUtils.getGenericSuperClassActualType(clazz, 0);
	}

	/**
	 * <pre>
	 * 2009/1/12 Timothy
	 * 	獲取 class 繼承超類的泛型宣告，迭代獲取最近的一個超類的泛型宣告列表中，
	 *  索引參數&lt;code&gt;index&lt;/code&gt;指向的類別，且限定與 genericClass 超類之內
	 * </pre>
	 * 
	 * @param clazz
	 *          需要獲取泛型宣告的當前class
	 * @param index
	 *          索引參數，指定獲取的參數類別
	 * @param genericClass
	 *          限定獲取的泛型宣告比一定繼承自 genericClass
	 * @return 獲取 class 繼承超類的泛型宣告
	 * @throws com.WmsFrameworkException.VisualsoftFrameworkException
	 *           當 index < 0
	 * @see #getGenericSuperClassActualType(Class, int, Class)
	 */
	public static Class<?> getGenericSuperClassActualType(Class<?> clazz, int index, Class<?> genericClass) {

		if (clazz == Object.class) {
			return null;
		}

		Class<?> resultClass = VSClassUtils.getGenericSuperClassActualType(clazz, index);

		if (genericClass == Object.class) {
			return resultClass;
		}

		if ((resultClass == null) || !(genericClass.isAssignableFrom(resultClass))) {

			resultClass = VSClassUtils.getGenericSuperClassActualType(clazz.getSuperclass(), index, genericClass);
		}

		return resultClass;
	}

	/**
	 * <pre>
	 * 2009/1/12 Timothy
	 * 	獲取 class 繼承超類的泛型宣告，迭代獲取第一個限定與 genericClass 超類之內的泛型宣告
	 * </pre>
	 * 
	 * @param clazz
	 *          需要獲取泛型宣告的當前class
	 * @param genericClass
	 *          限定獲取的泛型宣告比一定繼承自 genericClass
	 * @return 獲取 class 繼承超類的泛型宣告
	 * @see #getGenericSuperClassActualType(Class)
	 * @see #getGenericSupreClassActualTypes(Class)
	 */
	public static Class<?> getGenericSuperClassActualType(Class<?> clazz, Class<?> genericClass) {

		if (genericClass == Object.class) {
			return VSClassUtils.getGenericSuperClassActualType(clazz);
		}

		Class<?> resultClass = null;
		List<Class<?>> genericSupreClassActualTypes = VSClassUtils.getGenericSupreClassActualTypes(clazz);

		if (!genericSupreClassActualTypes.isEmpty()) {

			for (Class<?> genericSupreClassActualType : genericSupreClassActualTypes) {

				if (genericClass.isAssignableFrom(genericSupreClassActualType)) {
					resultClass = genericSupreClassActualType;
					break;
				}
			}

			if (resultClass == null) {

				resultClass = VSClassUtils.getGenericSuperClassActualType(clazz.getSuperclass(), genericClass);
			}
		}

		return resultClass;
	}

}
